package fst

import fst.parsing._


trait Parsing extends MoreCombinators with StdTokenParsers {
  trait Term
  case class Var(n: String) extends Term  
  case class E(a: Term, b: Term) extends Term
  case class T(a: Term, b: Term) extends Term
  case class F(a: Term, b: Term) extends Term
  case class P(a: Term) extends Term

  def pE: Parser[Term] = chainl1(pT, ("+" | "-" ) ^^ const{(a: Term, b: Term) => E(a, b)})
  def pT: Parser[Term] = chainl1(pF, ( "*" | "/" ) ^^ const{(a: Term, b: Term) => T(a, b)})
  def pF: Parser[Term] = pP ~ opt("^" ~> pF) ^^ {case x ~ None => x  case x ~ Some(y) => F(x, y)}
  def pP: Parser[Term] = (ident ^^ {case n => Var(n)}) | ("(" ~> pE <~ ")") | (("-" ~> pT) ^^ P)

  
  type Lexical = StdLexical
  val lexical = new StdLexical
  lexical.delimiters += ("(", ")", "+", "-", "*", "/", "^")
//  lexical.reserved += ("true", "false", "Bool")
  import lexical.EOF

 
  def parse(input: String): Result[Term] = (pE <~ EOF)(input) match {
    case ns: NoSuccess => bestNoSuccess getOrElse Failure("unknown failure!!", input)
    case s => s
  }
}

object ParsingTest extends Parsing {
  def main(args: Array[String]) = println(parse(args(0)))
}